from math import floor

from flask import current_app
from flask_login import UserMixin
from sqlalchemy import Column, Integer, String, Boolean, Float
from apps import login_manager
from apps.models.drift import Drift
from apps.models.gift import Gift
from apps.models.wish import Wish
from apps.spider.yushu_book import YuShuBook
from apps.utils.enum import PendingStatus
from apps.utils.helper import word_type
from .base import Base, db
from werkzeug.security import generate_password_hash, check_password_hash
from itsdangerous import TimedJSONWebSignatureSerializer as TJWS


class User(Base, UserMixin):
    __tablename__ = 'user'
    # __bind_key__ = 'fisher'

    id = Column(Integer, primary_key=True)
    nickname = Column(String(24), nullable=False)
    phone_number = Column(String(18), unique=True)
    email = Column(String(50), unique=True, nullable=False)
    _password = Column('password', String(100), nullable=False)
    confirmed = Column(Boolean, default=False)
    beans = Column(Float, default=0)
    send_counter = Column(Integer, default=0)
    receive_counter = Column(Integer, default=0)
    wx_open_id = Column(String(50))
    wx_name = Column(String(32))

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, raw_pwd):
        self._password = generate_password_hash(raw_pwd)

    def check_password(self, raw_pwd):
        return check_password_hash(self.password, raw_pwd)

    def save_to_gift(self, isbn):
        if word_type(isbn) != 'isbn':
            return False
        book = YuShuBook()
        book.search_by_isbn(isbn)
        if book.count == 0:
            return False
        gifts = Gift.query.filter_by(uid=self.id, isbn=isbn, launched=False).first()
        wishes = Wish.query.filter_by(uid=self.id, isbn=isbn, launched=False).first()
        if gifts or wishes:
            return False
        return True

    def gene_token(self, expiration=600):
        tjws = TJWS(current_app.config['SECRET_KEY'], expiration)
        return tjws.dumps({'id': self.id}).decode('utf-8')

    @staticmethod
    def reset_pwd(token, new_pwd):
        tjws = TJWS(current_app.config['SECRET_KEY'])
        try:
            user_id = tjws.loads(token.encode('utf-8')).get('id')
        except:
            return False
        with db.auto_commit():
            user = User.query.get(user_id)
            user.password = new_pwd
        return True

    def is_self(self, gift):
        return self.id == gift.uid

    def is_qualified(self):
        gift_count = Gift.query.filter_by(uid=self.id, launched=True).count()
        recv_count = Drift.query.filter_by(requester_id=self.id, pending=PendingStatus.success).count()
        return True if floor(recv_count / 2) <= gift_count else False

    @property
    def summary(self):
        return dict(
            nickname=self.nickname,
            beans=self.beans,
            email=self.email,
            send_receive=str(self.send_counter) + '/' + str(self.receive_counter)
        )


@login_manager.user_loader
def get_user(uid):
    return User.query.get(uid)
